package cn.xinfei.xdecision.engine.runner.metadata;

import cn.xinfei.xdecision.common.dao.enginex.EngineMapper;
import cn.xinfei.xdecision.common.dao.enginex.EngineVersionMapper;
import cn.xinfei.xdecision.common.model.enginex.po.Engine;
import cn.xinfei.xdecision.common.model.enginex.po.EngineVersion;
import cn.xinfei.xdecision.common.model.enginex.vo.EngineVersionRespVo;
import cn.xinfei.xdecision.common.service.enginex.EngineVersionService;
import cn.xinfei.xdecision.common.utils.enums.enginex.EngineVersionStatusEnum;
import cn.xinfei.xdecision.thread.CustomerThreadPoolExecutor;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.google.common.collect.Tables;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@Slf4j
@Service
public class EngineInfoLoader {

    @Autowired
    private EngineMapper engineMapper;

    @Autowired
    private EngineVersionMapper engineVersionMapper;

    @Resource
    private EngineVersionService engineVersionService;

    @Resource(name = "metadataCacheReloadThreadPool")
    public CustomerThreadPoolExecutor metadataCacheReloadThreadPool;

    public Table<String, Long, Engine> init(String engineCd) {
        log.info("EngineInfoLoader start");
        Table<String, Long, Engine> engineAndVersionMap = Tables.synchronizedTable(HashBasedTable.create());
        long start=System.currentTimeMillis();
        LambdaQueryWrapper<Engine> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Engine::getDeleted, 0);
        if (StringUtils.isNotEmpty(engineCd)) {
            queryWrapper.eq(Engine::getCode, engineCd);
        }
        List<Engine> engines = engineMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(engines)) {
            CountDownLatch countDownLatch = new CountDownLatch(engines.size());
            for (Engine engine : engines) {
                metadataCacheReloadThreadPool.submit(() -> {
                    String engineCode = engine.getCode();
                    try {
                        //理论上只有一条运行中的版本
//                        LambdaQueryWrapper<EngineVersion> wrapper = new LambdaQueryWrapper<>();
//                        wrapper.eq(EngineVersion::getStatus, EngineVersionStatusEnum.ENABLE.getStatus());
//                        wrapper.eq(EngineVersion::getEngineCode, engineCode);
                        EngineVersion runningVersion = engineVersionService.getRunningVersion(engineCode);
                        if (null != runningVersion) {
                            Long versionNo = runningVersion.getVersionNo();
                            engineAndVersionMap.put(engineCode, versionNo, engine);
                        } else {
//                        log.warn("engineCode={}  不存在运行中的版本数据", engineCode);
                        }
                    } catch (Exception e) {
                        log.info("reload engine config engineCode={}, error:{}", engineCode, e.getMessage(), e);
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        long end=System.currentTimeMillis();
        log.info("EngineInfoLoader end.size={},duration={}", engineAndVersionMap.size(),end-start);
        return engineAndVersionMap;
    }

    /**
     * 不考虑版本是否运行中
     *
     * @param engineCd
     * @return
     */
    public Table<String, Long, Engine> getEngineInfo(String engineCd,long versionNo) {
        log.info("EngineInfoLoader start");
        long start=System.currentTimeMillis();
        Table<String, Long, Engine> engineAndVersionMap = Tables.synchronizedTable(HashBasedTable.create());

        LambdaQueryWrapper<Engine> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Engine::getDeleted, 0);
        if (StringUtils.isNotEmpty(engineCd)) {
            queryWrapper.eq(Engine::getCode, engineCd);
        }
        List<Engine> engines = engineMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(engines)) {
            CountDownLatch countDownLatch = new CountDownLatch(engines.size());
            for (Engine engine : engines) {
                metadataCacheReloadThreadPool.submit(() -> {
                    String engineCode = engine.getCode();
                    try {
                        List<EngineVersion> runningVersion = engineVersionService.getRunningVersionList(engineCode,versionNo);
                        if (null != runningVersion && runningVersion.size() > 0) {
                            for (EngineVersion version : runningVersion) {
                                Long versionNo1 = version.getVersionNo();
                                engineAndVersionMap.put(engineCode, versionNo1, engine);
                            }
                        } else {
//                        log.warn("engineCode={}  不存在运行中的版本数据", engineCode);
                        }
                    } catch (Exception e) {
                        log.info("reload engine config engineCode={}, error:{}", engineCode, e.getMessage(), e);
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            try {
                countDownLatch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        long end=System.currentTimeMillis();
        log.info("EngineInfoLoader end.size={},suration={}", engineAndVersionMap.size(),end-start);
        return engineAndVersionMap;
    }
}
